package com.sky.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传 - 按日期分类存储
     *
     * @param bytes 文件字节数组
     * @param originalFileName 原始文件名
     * @return 文件访问URL
     */
    public String upload(byte[] bytes, String originalFileName) {
        // 生成按日期分类的对象名称
        String objectName = generateDateBasedObjectName(originalFileName);
        return uploadWithObjectName(bytes, objectName);
    }

    /**
     * 文件上传 - 指定对象名称
     *
     * @param bytes 文件字节数组
     * @param objectName 指定的对象名称
     * @return 文件访问URL
     */
    public String uploadWithObjectName(byte[] bytes, String objectName) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
            log.info("文件上传成功，对象名称: {}", objectName);

            // 生成文件访问路径
            String fileUrl = generateFileUrl(objectName);
            log.info("文件访问路径: {}", fileUrl);
            return fileUrl;

        } catch (OSSException oe) {
            log.error("OSS异常: Error Message: {}, Error Code: {}, Request ID: {}, Host ID: {}",
                    oe.getErrorMessage(), oe.getErrorCode(), oe.getRequestId(), oe.getHostId());
            throw new RuntimeException("文件上传失败: " + oe.getErrorMessage(), oe);
        } catch (ClientException ce) {
            log.error("客户端异常: {}", ce.getMessage());
            throw new RuntimeException("文件上传失败: " + ce.getMessage(), ce);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 生成按日期分类的对象名称
     * 格式: yyyy/MM/dd/uuid_originalFileName
     *
     * @param originalFileName 原始文件名
     * @return 生成的对象名称
     */
    private String generateDateBasedObjectName(String originalFileName) {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        String datePath = currentDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

        // 生成唯一文件名（防止重名）
        String fileExtension = getFileExtension(originalFileName);
        String uniqueFileName = generateUniqueFileName(originalFileName);

        // 组合完整路径
        return datePath + "/" + uniqueFileName + fileExtension;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf("."));
    }

    /**
     * 生成唯一文件名
     */
    private String generateUniqueFileName(String originalFileName) {
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);

        if (originalFileName == null || originalFileName.isEmpty()) {
            return uuid;
        }

        // 提取文件名（不含扩展名）
        String nameWithoutExtension;
        if (originalFileName.contains(".")) {
            nameWithoutExtension = originalFileName.substring(0, originalFileName.lastIndexOf("."));
        } else {
            nameWithoutExtension = originalFileName;
        }

        // 限制文件名长度，避免过长
        if (nameWithoutExtension.length() > 50) {
            nameWithoutExtension = nameWithoutExtension.substring(0, 50);
        }

        // 移除特殊字符，只保留字母数字和下划线
        nameWithoutExtension = nameWithoutExtension.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5_]", "_");

        return nameWithoutExtension + "_" + uuid;
    }

    /**
     * 生成文件访问URL
     */
    private String generateFileUrl(String objectName) {
        // 文件访问路径规则: https://BucketName.Endpoint/ObjectName
        return String.format("https://%s.%s/%s", bucketName, endpoint, objectName);
    }

    /**
     * 按自定义日期格式生成对象名称
     *
     * @param bytes 文件字节数组
     * @param originalFileName 原始文件名
     * @param dateFormat 日期格式，如 "yyyy/MM" 或 "yyyy-MM/dd"
     * @return 文件访问URL
     */
    public String uploadWithCustomDateFormat(byte[] bytes, String originalFileName, String dateFormat) {
        String objectName = generateCustomDateObjectName(originalFileName, dateFormat);
        return uploadWithObjectName(bytes, objectName);
    }

    /**
     * 生成自定义日期格式的对象名称
     */
    private String generateCustomDateObjectName(String originalFileName, String dateFormat) {
        LocalDate currentDate = LocalDate.now();
        String datePath = currentDate.format(DateTimeFormatter.ofPattern(dateFormat));

        String fileExtension = getFileExtension(originalFileName);
        String uniqueFileName = generateUniqueFileName(originalFileName);

        return datePath + "/" + uniqueFileName + fileExtension;
    }
}